#! usr/bin/env python
# ididdocontroller.py
from datetime import date, datetime

from ididdomodel import TodoItemDB
from ididdomodel import TodoItemModel

from ididdoview import CommandLineView
from ididdoview import ConkyView

from optparse import OptionGroup
from optparse import OptionParser
from optparse import OptionValueError

__author__ = "Tiago Seixas"
__copyright__ = "Copyright 2011, Tiago Seixas"
__credits__ = ["Tiago Seixas"]
__license__ = "GPL"
__version__ = "3"
__maintainer__ = "Tiago Seixas"
__email__ = "tiagoafseixas@gmail.com"
__status__ = "Prototype"

def process_params(values):
    dict_params = {}

    if values.title:
        dict_params['title'] = values.title
        
    if values.project:
        dict_params['project'] = values.project

    if values.priority:
        try:
            dict_params['priority'] = int(values.priority)
        except:
            raise OptionValueError('Priority must be an integer')

    if values.where:
        dict_params['where'] = values.where
        
    if values.done is not None:
        dict_params['done'] = values.done
        
    if values.when:
        dict_params['when'] = values.when

    return dict_params


class TodoListController(object):
    def __init__(self):
        pass

    def list(self, option, opt, value, parser):
        parser.parse_args(parser.rargs)
        values = parser.values

        if values.verbose == True:
            print('> @list')

        if not values.cmd_line and not values.conky:
            raise OptionValueError('Choose either -c or -C.')
        
        dict_params = process_params(values)

        if values.verbose == True:
            print(dict_params)

        if values.today == True:
            dict_params['when'] = date.today().isoformat()

        #!!!TODO:handle order
        db = TodoItemDB()
        todo_list = db.find(dict_params)

        if values.cmd_line is not None:
            view = CommandLineView(todo_list)
        elif values.conky is not None:
            view = ConkyView(todo_list, values.format, values.separator)

        view.render()


class TodoItemController:
    def __init__(self):
        pass

    def delete_item(self, option, opt, value, parser):
        parser.parse_args(parser.rargs)
        values = parser.values

        if values.verbose == True:
            print('> @delete')

        if values.id is None:
            raise OptionValueError('The option -i is mandatory.')

        ref_id = None

        try:
            ref_id = int(values.id)
        except ValueError:
            raise OptionValueError('The id of the item must be an integer.')

        db = TodoItemDB()
        db.remove(ref_id)

    def update_item(self, option, opt, value, parser):
        parser.parse_args(parser.rargs)
        values = parser.values

        if values.verbose == True:
            print('> @update')

        if values.id is None:
            raise OptionValueError('The option -i is mandatory.')

        ref_id = None

        try:
            ref_id = int(values.id)
        except ValueError:
            raise OptionValueError('The id of the item must be an integer.')

        if values.verbose == True:
            print('Incoming Values :' + str(values))

        todo_item = process_params(values)

        if values.verbose == True:
            print('Processed Values:' + str(todo_item))

        db = TodoItemDB()
        db.update(ref_id, todo_item)
        
    def add_item(self, option, opt, value, parser):
        parser.parse_args(parser.rargs)
        values = parser.values

        if values.verbose == True:
            print('> @add')

        if values.id:
            raise OptionValueError('Can\'t use -i in add item.')

        if not values.title:
            raise OptionValueError('The option -t is mandatory.')

        if not values.priority:
            values.priority = 5

        todo_item = {
            'title'    : values.title,
            'priority' : int(values.priority),
            'created'  : date.today().isoformat(),
            'where'    : values.where
            }

        if values.when:
            todo_item['when'] = values.when

        if values.project:
            todo_item['project'] = values.project

        if values.verbose == True:
            print('> adding item: ')
            print(todo_item)

        model = TodoItemModel(todo_item)
        db = TodoItemDB()
        db.insert(model)


class CommandLineDispatcher:
    def __init__(self):
        pass
    
    def _init_parser(self):
        usage = 'usage: %prog [options]'
        self.parser = OptionParser(usage=usage,
                                   version='%prog v0.3')

        #base options#
        main_group = OptionGroup(self.parser, 'Main Options')
        main_group.add_option('-a', '--add',
                              action='callback',
                              callback=TodoItemController().add_item,
                              help='Add a new Item')
        main_group.add_option('-r', '--rem',
                              action='callback',
                              callback=TodoItemController().delete_item,
                              help='Remove a Item')
        main_group.add_option('-u', '--update',
                              action='callback',
                              callback=TodoItemController().update_item,
                              help='Update a Item')
        main_group.add_option('-l', '--list',
                              action='callback',
                              callback=TodoListController().list,
                              help='List all items')
        main_group.add_option('-v', '--verbose',
                              action='store_true',
                              help='Verbose Mode')

        self.parser.add_option_group(main_group)

        #specific item options#
        group = OptionGroup(self.parser, 'Item Options')
        group.add_option('-t', '--title',
                         dest='title',
                         help='Title of the item. Recommended usage: -t"<title ' \
                             'with spaces>".')
        group.add_option('-w', '--where',
                         dest='where',
                         help='Where the item can be executed.')
        group.add_option('-p', '--project',
                         dest='project',
                         help='The name of the project.')
        group.add_option('-d', '--due',
                         dest='when',
                         help='The due date for the item.')
        group.add_option('-P', '--priority',
                         dest='priority',
                         help='The priority of the item.')
        group.add_option('-i', '--id',
                         dest='id',
                         help='The id of the item. Used in the remove and update.')
        group.add_option('-D', '--done',
                         dest='done',
                         action='store_true',
                         help='Use this flag in update to mark an item as done.')
        group.add_option('-N', '--notdone',
                         dest='done',
                         action='store_false',
                         help='Use this flag in update to mark an item as not done.')

        self.parser.add_option_group(group)

        #list item options#
        list_group = OptionGroup(self.parser, 'List Item Options')
        list_group.add_option('-c', '--cmd_line',
                              dest='cmd_line',
                              action='store_true',
                              help='Formats the output for the command line')
        list_group.add_option('-C', '--conky',
                              dest='conky',
                              action='store_true',
                              help='Formats the output for Conky')
        #!!!TODO: Not Implemented!
        list_group.add_option('-o', '--order',
                              dest='order',
                              help='The order of the list.')

        list_group.add_option('-T', '--today',
                              dest='today',
                              action='store_true',
                              help='Get today\'s to-do items.')
        list_group.add_option('-f', '--format',
                              dest='format',
                              default=None,
                              help='The output format for each item in the list.')
        list_group.add_option('-s', '--separator',
                              dest='separator',
                              default=None,
                              help='The item field separator in the description.')

        self.parser.add_option_group(list_group)

    def run(self):
        self._init_parser()
        self.parser.parse_args()
        
if __name__ == '__main__':
    cld = CommandLineDispatcher()
    cld.run()
